# Copyright (c) 2022 Presto Labs Pte. Ltd.
# Author: junglekim

import json
import string
import random
import os
import ast
import pathlib

from cc.appcoin2.strategy.sim_backtest import SimBacktest
from cc.appcoin2.strategy.vmm.support.util import (get_prefix, StratConfigVmm)


class VmmBacktest(SimBacktest):
  def __init__(
      self,
      tmp_dirname,
      analyzer_feed_machine,
      *,
      init_edge_bp=None,
      window_size_minute=None,
      basket_size_minute=None,
      default_edge_bp=None,
      max_edge_bp=None,
      decay_min=None,
      reserve=None,
      lot_size=None,
      max_pos=None,
      min_pos=None,
      sticky_bp=None,
      dodge_edge_bp=None,
      min_value=None,
      bandwidth_bp=None,
      num=None,
      strike_price=None,
      risk_free_rate=None,
      volatility=None,
      expiry=None,
      call_num=None,
      move_bp=None,
      move_sec=None,
      logspace_start=None,
      logspace_stop=None,
      logspace_num=None,
      grid_period_hour=None,
      pos_diff_allowance_percentage=None,
      calc_real_delta_hour=None,
      min_spread_bp=None,
      qty_tolerance_bp=None,
      pos_offset=None,
      randomise=None,
      is_approach=None,
      initial_pos=None,
      volatility_thold=None,
      initial_deco_fill_day_usage_ratio=None,
      market_window_sec=None,
      midp_interval_ms=None,
      agg_min_quote=None,
      pass_min_quote=None,
      agg_arb_thold_bp=None,
      pass_arb_thold_bp=None,
      agg_order_frequency_sec=None,
      pass_order_frequency_sec=None,
      min_twap_pricing_weight=None,
      deco_twap_decay=None,
      cancel2order_ratio=None,
      is_randomize_post=None,
      arb_full_book_num=None,
      verbose=0,
      include_tag_info=None,
      pick_symbol_regex=None,#
      worker=None,#
      machine=None,#
      **kwargs):
    super().__init__(tmp_dirname, analyzer_feed_machine, **kwargs)
    self._verbose = 1 if verbose == 1 else 0
    self.include_tag_info = include_tag_info
    self.params = {
        "init_edge_bp": init_edge_bp,
        "window_size_minute": window_size_minute,
        "basket_size_minute": basket_size_minute,
        "default_edge_bp": default_edge_bp,
        "max_edge_bp": max_edge_bp,
        "decay_min": decay_min,
        "lot_size": lot_size,
        "sticky_bp": sticky_bp,
        "dodge_edge_bp": dodge_edge_bp,
        "min_value": min_value,
        "bandwidth_bp": bandwidth_bp,
        "num": num,
        "strike_price": strike_price,
        "risk_free_rate": risk_free_rate,
        "volatility": volatility,
        "expiry": expiry,
        "call_num": call_num,
        "move_bp": move_bp,
        "move_sec": move_sec,
        "logspace_start": logspace_start,
        "logspace_stop": logspace_stop,
        "logspace_num": logspace_num,
        "grid_period_hour": grid_period_hour,
        "pos_diff_allowance_percentage": pos_diff_allowance_percentage,
        "calc_real_delta_hour": calc_real_delta_hour,
        "min_spread_bp": min_spread_bp,
        "qty_tolerance_bp": qty_tolerance_bp,
        "randomise": randomise,
        "reserve": reserve,
        "max_pos": max_pos,
        "min_pos": min_pos,
        "is_approach": is_approach,
        "initial_pos": initial_pos,
        "pos_offset": pos_offset,
        "volatility_thold": volatility_thold,
        "initial_deco_fill_day_usage_ratio": initial_deco_fill_day_usage_ratio,
        "market_window_sec": market_window_sec,
        "midp_interval_ms": midp_interval_ms,
        "agg_min_quote": agg_min_quote,
        "pass_min_quote": pass_min_quote,
        "agg_arb_thold_bp": agg_arb_thold_bp,
        "pass_arb_thold_bp": pass_arb_thold_bp,
        "agg_order_frequency_sec": agg_order_frequency_sec,
        "pass_order_frequency_sec": pass_order_frequency_sec,
        "min_twap_pricing_weight": min_twap_pricing_weight,
        "deco_twap_decay": deco_twap_decay,
        "arb_full_book_num": arb_full_book_num,
        "cancel2order_ratio": cancel2order_ratio,
        "is_randomize_post": is_randomize_post,
    }
    self.params = {k: self.params[k] for k in sorted(self.params)}
    self.pick_symbol_regex = pick_symbol_regex
    self.worker = worker or 0
    self.params.update({'config_file': self.config_path})
    self.strat_prefix = get_prefix(self.params)
    self.sim_binary = '../coin_binary/coin2-bazel-bin-3.10/cc/appcoin2/strategy/vmm/vmm_sim_runner'

    self.driver_config_filenames = {}
    self.strat_config_filename = {}
    self.vmm_strat_config = None

  def cmd_prerun_on_date(self, trading_interval, i):
    st = trading_interval[0].strftime('%Y%m%dT%H%M%S')
    et = trading_interval[1].strftime('%Y%m%dT%H%M%S')
    population = string.ascii_letters + string.digits
    res = random.choices(population, k=6)

    driver_filename = f'{self.sim_result_dir}/drivers/{self.strat_prefix}_{"".join(res)}.json'
    config_filename = f'{self.sim_result_dir}/configs/{self.strat_prefix}.json'

    self.driver_config_filenames[i] = driver_filename
    self.strat_config_filename[i] = config_filename

    cmd = f"""./pyrunner  \
      cc/experimental/lucasyoo/config_gen.py  \
      --analyzer_feed_machine={self.analyzer_feed_machine}  \
      --config_path={self.config_path} \
      --is_sim={True} \
      --driver_file_name={driver_filename} \
      --config_file_name={config_filename} \
      --start_dt={st} \
      --end_dt={et} \
      --params={"'" + json.dumps(ast.literal_eval(str(self.params))) + "'"} \
      --tmp_dirname={self.tmp_dirname} \
      --sim_result_dir={self.sim_result_dir} \
      --strategy_group=vmm \
      --is_approach={False if not self.params['is_approach'] else True} \
      --initial_pos={0.0 if self.params['initial_pos'] is None else self.params['initial_pos']} \
      --include_tag_info={self.include_tag_info} \
        $> /dev/null"""
    print(cmd)
    return cmd

  def cmd_run_on_date(self, trading_interval, i):
    if self.config_path is None:
      return

    from_dt_str = trading_interval[0].strftime("%Y%m%dT%H%M%S")
    cmd_sim = f"""{self.sim_binary} \
--driver={self.driver_config_filenames[i]} \
--strat_config={self.strat_config_filename[i]} \
--verbose {1 if self._verbose else 0} \
&> {self.tmp_dirname}/log{from_dt_str}.txt"""
    print(cmd_sim)
    cmdpath = pathlib.Path(f'{self.sim_result_dir}/log_runsim_cmd.txt')
    if cmdpath.is_file():
      content = cmdpath.read_text() + cmd_sim + '\n'
    else:
      content = cmd_sim + '\n'
    cmdpath.write_text(content)
    return cmd_sim
